package co.edu.unal.bioingenium.kbmed.knowledge.services.impl;

import co.edu.unal.bioingenium.kbmed.knowledge.KnowledgeService;
import co.edu.unal.bioingenium.kbmed.knowledge.KnowledgeSourceMetaData;
import co.edu.unal.bioingenium.kbmed.knowledge.snomed.SnomedMetaData;
import co.edu.unal.bioingenium.kbmed.knowledge.services.api.KnowledgeWebService;
import co.edu.unal.bioingenium.kbmed.knowledge.similarity.SemanticSimilartyService;
import co.edu.unal.bioingenium.kbmed.knowledge.similarity.SemanticSimilartyService.SemanticSimilarityFunction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.jws.WebService;

/**
 * @author Ryan Heaton
 */
@WebService(endpointInterface = "co.edu.unal.bioingenium.kbmed.knowledge.services.api.KnowledgeWebService")
public class KnowledgeWebServiceImpl implements KnowledgeWebService {

    private KnowledgeService knowledgeService;
    private SemanticSimilartyService similartyService;
    private Map<String, SemanticSimilarityFunction> similarityFunctionsMap;

    /**
     * 
     */
    public KnowledgeWebServiceImpl() {
        knowledgeService = KnowledgeService.getInstance();
        similartyService = SemanticSimilartyService.getInstance();
        similarityFunctionsMap = new HashMap<String, SemanticSimilarityFunction>();
        for (SemanticSimilarityFunction semanticSimilarityFunction : SemanticSimilarityFunction.values()) {
            similarityFunctionsMap.put(semanticSimilarityFunction.getName(), semanticSimilarityFunction);
        }
    }

    public Set<String> getSemanticSimilarityNames() {
        return similartyService.getSemanticSimilarityNames();
    }

    public String getConceptIdForDescriptorId(String descriptorId) {
        return knowledgeService.getCategoryForDescriptorId(descriptorId);
    }

    /**
     * 
     * @param descriptorId
     * @return
     */
    public String getTermForDescriptorId(String descriptorId) {
        return knowledgeService.getTermForDescriptorId(descriptorId);
    }

    /**
     * 
     * @param conceptId
     * @return
     */
    public Set<String> getTermsByConceptId(String conceptId) {
        return knowledgeService.getTermsByConceptId(conceptId);
    }

    /**
     * 
     * @param conceptId
     * @return
     */
    public String getCategoryForConceptId(String conceptId) {
        return knowledgeService.getCategoryForConceptId(conceptId);
    }

    public String getCategoryForDescriptorId(String descriptorId) {
        return knowledgeService.getCategoryForDescriptorId(descriptorId);
    }

    /**
     * 
     * @param conceptId
     * @return
     */
    public List<String> getPathToRootByConceptId(String conceptId) {
        return knowledgeService.getPathToRootByConceptId(conceptId);
    }

    public List<String> getPathToRootByDescriptorId(String descriptorId) {
        return knowledgeService.getPathToRootByDescriptorId(descriptorId);
    }

    /**
     * 
     * @param conceptId
     * @return
     */
    public Set<String> getDirectParentsByConceptId(String conceptId) {
        return knowledgeService.getDirectParentsByConceptId(conceptId);
    }

    public Set<String> getDirectParentsByDescriptorId(String descriptorId) {
        return knowledgeService.getDirectParentsByDescriptorId(descriptorId);
    }

    /**
     * 
     * @param conceptId
     * @return
     */
    public Set<String> getDirectChildrensByConceptId(String conceptId) {
        return knowledgeService.getDirectChildrensByConceptId(conceptId);
    }

    public Set<String> getDirectChildrensByDescriptorId(String descriptorId) {
        return knowledgeService.getDirectChildrensByDescriptorId(descriptorId);
    }

    /**
     * 
     * @param conceptId
     * @return
     */
    public Set<String> getDirectSiblingsByConceptId(String conceptId) {
        return knowledgeService.getDirectSiblingsByConceptId(conceptId);
    }

    public Set<String> getDirectSiblingsByDescriptorId(String descriptorId) {
        return knowledgeService.getDirectSiblingsByDescriptorId(descriptorId);
    }

    /**
     * 
     * @param conceptId
     * @return
     */
    public Set<String> getNeighborsByConceptId(String conceptId) {
        return knowledgeService.getNeighborsByConceptId(conceptId);
    }

    public Set<String> getNeighborsByDescriptorId(String descriptorId) {
        return knowledgeService.getNeighborsByDescriptorId(descriptorId);
    }

    /**
     * 
     * @param conceptId1
     * @param conceptId2
     * @param semanticSimilarityFunction 
     * @return
     */
    public float getSemanticSimilarityByConceptId(String conceptId1, String conceptId2, String semanticSimilarityFunction) {
        return similartyService.getSemanticSimilarityByConceptId(conceptId1, conceptId2, similarityFunctionsMap.get(semanticSimilarityFunction));
    }

    /**
     * 
     * @param conceptIds
     * @param semanticSimilarityFunction 
     * @return
     */
    public float[] getSemanticSimilaritysByConceptIds(List<String> conceptIds, String semanticSimilarityFunction) {
        float[][] simMatrix = similartyService.getSemanticSimilaritysByConceptIds(conceptIds, similarityFunctionsMap.get(semanticSimilarityFunction));
        int numConcepts = conceptIds.size();
        float[] simVector = new float[numConcepts * numConcepts];
        for (int i = 0; i < numConcepts; i++) {
            System.arraycopy(simMatrix[i], 0, simVector, i * numConcepts, numConcepts);
        }
        return simVector;
    }

    /**
     * 
     * @param descriptorId1
     * @param descriptorId2
     * @param semanticSimilarityFunction 
     * @return
     */
    public float getSemanticSimilarityByDescriptorId(String descriptorId1, String descriptorId2, String semanticSimilarityFunction) {
        String tempConceptId1, tempConceptId2;
        tempConceptId1 = knowledgeService.getConceptIdForDescriptorId(descriptorId1);
        tempConceptId2 = knowledgeService.getConceptIdForDescriptorId(descriptorId2);
        return getSemanticSimilarityByConceptId(tempConceptId1, tempConceptId2, semanticSimilarityFunction);

    }

    /**
     * 
     * @param descriptorIds
     * @param semanticSimilarityFunction 
     * @return
     */
    public float[] getSemanticSimilaritysByDescriptorIds(List<String> descriptorIds, String semanticSimilarityFunction) {
        List<String> tempConceptsIds = new ArrayList<String>(descriptorIds.size());
        for (int i = 0; i < descriptorIds.size(); i++) {
            tempConceptsIds.add(i, knowledgeService.getConceptIdForDescriptorId(descriptorIds.get(i)));
        }
        return getSemanticSimilaritysByConceptIds(tempConceptsIds, semanticSimilarityFunction);
    }
}
